package org.linlinjava.litemall.mechanismadmin.web;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.systemConfig.GetRegionService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallAddress;
import org.linlinjava.litemall.db.domain.LitemallRegion;
import org.linlinjava.litemall.db.service.LitemallAddressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/mechanism/address")
public class MechanismAddressController extends GetRegionService {
	private final Log logger = LogFactory.getLog(MechanismAddressController.class);

	@Autowired
	private LitemallAddressService addressService;

	@Resource
	private RedisTemplate redisTemplate;

	@Autowired
	private PlatformTransactionManager txManager;

	/**
	 * 用户收货地址列表
	 *
	 * @param userId 用户ID
	 * @return 收货地址列表
	 */
	@GetMapping("list")
	public Object list(Integer userId) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		String key = "addressByMechUser" + userId;
		// 缓存存在
		boolean hasKey = redisTemplate.hasKey(key);
		if (hasKey) {
			// 从缓存中取
			List data = redisTemplate.opsForList().range(key, 0, -1);
			System.out.println("从缓存取");
			return ResponseUtil.ok(data);
		} else {
			Boolean mtype = true;
			List<LitemallAddress> addressList = addressService.queryByUid(userId, mtype);
			List<Map<String, Object>> addressVoList = new ArrayList<>(addressList.size());
			List<LitemallRegion> regionList = getLitemallRegions();
			for (LitemallAddress address : addressList) {
				Map<String, Object> addressVo = new HashMap<>(16);
				addressVo.put("id", address.getId());
				addressVo.put("name", address.getName());
				addressVo.put("mobile", address.getMobile());
				addressVo.put("isDefault", address.getIsDefault());
				String province = regionList.stream().filter(region -> region.getId().equals(address.getProvinceId())).findAny().orElse(null).getName();
				String city = regionList.stream().filter(region -> region.getId().equals(address.getCityId())).findAny().orElse(null).getName();
				String area = regionList.stream().filter(region -> region.getId().equals(address.getAreaId())).findAny().orElse(null).getName();
				String addr = address.getAddress();
				String detailedAddress = province + city + area + " " + addr;
				addressVo.put("detailedAddress", detailedAddress);
				redisTemplate.opsForList().rightPushAll(key, addressVo);
				redisTemplate.expire(key, 20, TimeUnit.MINUTES);
				addressVoList.add(addressVo);
			}
			System.out.println("查询库");
			return ResponseUtil.ok(addressVoList);
		}
	}

	/**
	 * 收货地址详情
	 *
	 * @param userId 用户ID
	 * @param id     收获地址ID
	 * @return 收货地址详情
	 * 成功则
	 * {
	 * errno: 0,
	 * errmsg: '成功',
	 * data:
	 * {
	 * id: xxx,
	 * name: xxx,
	 * provinceId: xxx,
	 * cityId: xxx,
	 * districtId: xxx,
	 * mobile: xxx,
	 * address: xxx,
	 * isDefault: xxx,
	 * provinceName: xxx,
	 * cityName: xxx,
	 * areaName: xxx
	 * }
	 * }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@GetMapping("detail")
	public Object detail(Integer userId, Integer id) {

		if (id == null) {
			return ResponseUtil.badArgument();
		}

		LitemallAddress address = addressService.findById(id);
		if (address == null) {
			return ResponseUtil.badArgumentValue();
		}
		List<LitemallRegion> regionList = getLitemallRegions();

		Map<Object, Object> data = new HashMap<Object, Object>();
		if (address != null) {
			data.put("id", address.getId());
			data.put("name", address.getName());
			data.put("mobile", address.getMobile());
			data.put("address", address.getAddress());
			data.put("isDefault", address.getIsDefault());
		} else {
			return ResponseUtil.fail();
		}
		Callable<String> pnameCallable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				String pname = regionList.stream().filter(region -> region.getId().equals(address.getProvinceId())).findAny().orElse(null).getName();
				return pname;
			}
		};
		Callable<String> pcodeCallable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				Integer pcode = regionList.stream().filter(region -> region.getId().equals(address.getProvinceId())).findAny().orElse(null).getCode();
				String pid = pcode + "";
				pid += "0000";
				return pid;
			}
		};
		Callable<String> cnameCallable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				String cname = regionList.stream().filter(region -> region.getId().equals(address.getCityId())).findAny().orElse(null).getName();
				return cname;
			}
		};
		Callable<String> cidCallable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				Integer ccode = regionList.stream().filter(region -> region.getId().equals(address.getCityId())).findAny().orElse(null).getCode();
				String cid = ccode + "";
				cid += "00";
				return cid;
			}
		};
		Callable<String> dnameCallable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				String dname = regionList.stream().filter(region -> region.getId().equals(address.getAreaId())).findAny().orElse(null).getName();
				return dname;
			}
		};
		Callable<Integer> acpdeCallable = new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				Integer acpde = regionList.stream().filter(region -> region.getId().equals(address.getAreaId())).findAny().orElse(null).getCode();
				return acpde;
			}
		};
		FutureTask<String> pnameTask = new FutureTask<>(pnameCallable);
		FutureTask<String> pcodeTask = new FutureTask<>(pcodeCallable);
		FutureTask<String> cnameTask = new FutureTask<>(cnameCallable);
		FutureTask<String> cidTask = new FutureTask<>(cidCallable);
		FutureTask<String> dnameTask = new FutureTask<>(dnameCallable);
		FutureTask<Integer> acpdeTask = new FutureTask<>(acpdeCallable);

		new Thread(pnameTask).start();
		new Thread(pcodeTask).start();
		new Thread(cnameTask).start();
		new Thread(cidTask).start();
		new Thread(dnameTask).start();
		new Thread(acpdeTask).start();

		try {
			data.put("provinceId", pcodeTask.get());
			data.put("cityId", cidTask.get());
			data.put("areaId", acpdeTask.get());
			data.put("provinceName", pnameTask.get());
			data.put("cityName", cnameTask.get());
			data.put("areaName", dnameTask.get());
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		return ResponseUtil.ok(data);
	}

	/**
	 * 添加或更新收货地址
	 *
	 * @param userId  用户ID
	 * @param address 用户收货地址
	 * @return 添加或更新操作结果
	 * 成功则 { errno: 0, errmsg: '成功' }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@GetMapping("save")
	public Object save(
		Integer id, Integer userId, String name, String mobile, Integer province_id, Integer city_id, Integer area_id, Boolean is_default, String address) {

		if (address == null) {
			return ResponseUtil.badArgument();
		}
		String province_ids = province_id + "";
		String city_ids = city_id + "";
		Integer province_idss = Integer.parseInt(province_ids.substring(0, 2));
		Integer city_idss = Integer.parseInt(city_ids.substring(0, 4));

		List<LitemallRegion> regionList = getLitemallRegions();
		Integer lastProvinceId = regionList.stream().filter(region -> region.getCode().equals(province_idss)).findAny().orElse(null).getId();
		Integer lastCityId = regionList.stream().filter(region -> region.getCode().equals(city_idss)).findAny().orElse(null).getId();
		Integer lastAreaId = regionList.stream().filter(region -> region.getCode().equals(area_id)).findAny().orElse(null).getId();
		LitemallAddress litemallAddress = new LitemallAddress();
		litemallAddress.setUserId(userId);
		litemallAddress.setName(name);
		litemallAddress.setMobile(mobile);
		litemallAddress.setProvinceId(lastProvinceId);
		litemallAddress.setCityId(lastCityId);
		litemallAddress.setAreaId(lastAreaId);
		litemallAddress.setMechanismType(true);
		litemallAddress.setIsDefault(is_default);
		litemallAddress.setAddress(address);

		//         开启事务管理
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		TransactionStatus status = txManager.getTransaction(def);
		try {
			if (is_default) {
				// 重置其他收获地址的默认选项
				addressService.resetMerchaismDefault(userId);

			}
			String key = "addressByMechUser" + userId;
			if (id == null || id.equals(0)) {
				// 新增取货地址
				litemallAddress.setAddTime(LocalDateTime.now());
				addressService.add(litemallAddress);
			} else {
				litemallAddress.setId(id);
				addressService.update(litemallAddress);
			}
			while (redisTemplate.opsForList().size((key)) > 0) {
				redisTemplate.opsForList().leftPop(key);
			}
		}
		catch (Exception ex) {
			txManager.rollback(status);
			return ResponseUtil.fail(-1, "保存失败");
		}
		txManager.commit(status);
		return ResponseUtil.ok(litemallAddress.getId());
	}

	/**
	 * 删除收货地址
	 *
	 * @param userId 用户ID
	 * @return 删除结果
	 * 成功则 { errno: 0, errmsg: '成功' }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@GetMapping("delete")
	public Object delete(Integer userId, Integer id) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}

		int num = addressService.delete(id);
		String key = "addressByMechUser" + userId;
		while (redisTemplate.opsForList().size((key)) > 0) {
			redisTemplate.opsForList().leftPop(key);
		}
		Map<String, Object> map = new HashMap<>(16);
		map.put("num", num);
		return ResponseUtil.ok(map);
	}

	@GetMapping("checkout")
	public Object checkout(Integer userId, Integer cartId, Integer addressId, Integer couponId) {

		// 收货地址
		LitemallAddress checkedAddress = null;
		if (addressId == null || addressId.equals(0)) {
			Boolean mtype = true;
			checkedAddress = addressService.findDefault(userId, mtype);

			// 如果仍然没有地址，则是没有收获地址
			// 返回一个空的地址id=0，这样前端则会提醒添加地址
			if (checkedAddress == null) {
				checkedAddress = new LitemallAddress();
				checkedAddress.setId(0);
				addressId = 0;
			} else {
				addressId = checkedAddress.getId();
			}

		} else {
			checkedAddress = addressService.findById(addressId);
			// 如果null, 则报错
			if (checkedAddress == null) {
				return ResponseUtil.badArgumentValue();
			}
		}

		Map<String, Object> data = new HashMap<>();
		data.put("addressId", addressId);
		data.put("checkedAddress", checkedAddress);
		data.put("couponId", couponId);
		data.put("checkedCoupon", 0);
		data.put("couponList", "");
		data.put("goodsTotalPrice", "");
		data.put("freightPrice", "");
		data.put("couponPrice", "");
		data.put("orderTotalPrice", "");
		data.put("actualPrice", "");
		data.put("checkedGoodsList", 0);
		//扣除爱能积分和爱币  赠送爱能积分和爱币
		data.put("deductIntegral", 0);
		data.put("deductPrice", 0);
		data.put("giveIntegral", 0);
		data.put("givePrice", 0);
		return ResponseUtil.ok(data);
	}
}